from dao.item import ItemDao
from model.advertisement import Advertisement
from dao.category import CategoryDao
from dao.house import HouseDao
from dao.user import UserDao
from bson.dbref import DBRef

class AdvertisementDao(ItemDao):
    def __init__(self):
        ItemDao.__init__(self, Advertisement)
        
        self.collection = 'advertisements'
        
        # category:[collection, Dao]
        self.items = {'house':['houses', HouseDao]}
        
    def insert(self, advertisement):
        """Save the object to collection
        Arguments:
            advertisement --- The Address Model object
        """
        if isinstance(advertisement, Advertisement):
            # Insert except ID field, because ID will be automatically generated
            _dict = {}
            _dict['prefer_contact'] = advertisement.prefer_contact;
            _dict['email'] = advertisement.email;
            _dict['phone'] = advertisement.phone;
            _dict['type'] = advertisement.type;
            _dict['created'] = advertisement.created;
            
            _dict['category'] = DBRef('categories', advertisement.category._id)
            
            collection = self.items[advertisement.category.name][0]
            _dict['item'] = DBRef( collection, advertisement.item._id );
            _dict['user'] = DBRef('users', advertisement.user._id );
            return self.db.insert(self.collection, _dict)
        
        return None
    
    
    def save(self, model):
        """Updates an existing document or inserts a new document, depending on its document parameter.
        Arguments:
            model --- The Model object with id if model is a dict type, the dbref field must be DBRef type
        Return:
            The '_id' value of to_save or [None] if manipulate is False and to_save has no _id field.
        """
        # The ID field must exist
        if isinstance(model, dict):
            return self.db.save(self.collection, model)
        else:            
            collection = self.items[model.category.name][0]
            
            # The __dict__ will modify object itself
            _dict = model.__dict__
            if _dict is not None:
                _dict['category'] = DBRef('categories', model.category._id)
                _dict['user'] = DBRef('users', model.user._id )
                
                
                _dict['item'] = DBRef(collection, model.item._id );
                
                return self.db.save(self.collection, _dict)
            else:
                return None
    
    def find_one(self, query):
        """
        Arguments:
            query --- The dict type
        Return:
            Raises TypeError if any of the arguments are of improper type. 
            Returns an instance of Cursor corresponding to this query.
        """
        _dict = self.db.find_one(self.collection, query)
        
        if _dict is not None:
            category_dbref = _dict['category']
            item_dbref = _dict['item']
            user_dbref = _dict['user']
            
            category_dao = CategoryDao()
            user_dao = UserDao()
            _dict['category'] = category_dao.find_one({'_id':category_dbref.id})
            _dict['user'] = user_dao.find_one({'_id':user_dbref.id})
            
            category_name = _dict['category'].name
            ItemDaoClass = self.items[category_name][1]
            item_dao = ItemDaoClass()
            _dict['item'] = item_dao.find_one({'_id':item_dbref.id})
            
            return self.ModelClass(_dict)
        else:
            return None
        
    def find(self, query={}):
        """
        Arguments:
            query --- The dict type
        Return:
            Raises TypeError if any of the arguments are of improper type. 
            Returns an instance of Cursor corresponding to this query.
        """
        cursor = self.db.find(self.collection, query=query)
        rets = []
        for _dict in cursor:
            category_dbref = _dict['category']
            item_dbref = _dict['item']
            user_dbref = _dict['user']
            
            category_dao = CategoryDao()
            user_dao = UserDao()
            _dict['category'] = category_dao.find_one({'_id':category_dbref.id})
            _dict['user'] = user_dao.find_one({'_id':user_dbref.id})
            
            category_name = _dict['category'].name
            ItemDaoClass = self.items[category_name][1]
            item_dao = ItemDaoClass()
            _dict['item'] = item_dao.find_one({'_id':item_dbref.id})
            
            rets.append(self.ModelClass(_dict))
        return rets  